package com.qn.sms.core.client.aliyun;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.AcsRequest;
import com.aliyuncs.AcsResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.qn.sms.core.client.dto.SmsSendRespDTO;
import com.qn.sms.core.client.impl.AbstractSmsClient;
import com.qn.sms.core.client.vo.SmsCommonResult;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

/**
 * 阿里短信客户端的实现类
 *
 * @author QN
 * @date 2022/02/26
 */
@Slf4j
public class AliyunSmsClient extends AbstractSmsClient {

    /**
     * REGION, 使用杭州
     */
    private static final String ENDPOINT = "cn-hangzhou";

    /**
     * 签名
     */
    public static final String SIGNATURE = "宁静博客";
    /**
     * access_key_id
     */
    public static final String ACCESS_KEY_ID = "LTAI4FzSz6A6zvRnot8drKLE";
    /**
     * secret
     */
    public static final String SECRET = "iostMfI5jwEv7sErKw2EZj4Nku4hmI";

    /**
     * 阿里云客户端
     */
    private IAcsClient client;

    @Override
    protected void doInit() {
        IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, ACCESS_KEY_ID, SECRET);
        client = new DefaultAcsClient(profile);
    }

    @Override
    protected SmsCommonResult<SmsSendRespDTO> doSendSms(String sendLogId, String mobile, String apiTemplateId, Map<String, Object> templateParams) throws Throwable {
        // 构建参数
        SendSmsRequest request = new SendSmsRequest();
        request.setPhoneNumbers(mobile);
        request.setSignName(SIGNATURE);
        request.setTemplateCode(apiTemplateId);
        request.setTemplateParam(JSON.toJSONString(templateParams));
        request.setOutId(sendLogId);
        // 执行请求
        return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId()));
    }

    <T extends AcsResponse, R> SmsCommonResult<R> invoke(AcsRequest<T> request, Function<T, R> responseConsumer) {
        try {

            // 执行发送. 由于阿里云 sms 短信没有统一的 Response，但是有统一的 code、message、requestId 属性，所以只好反射
            T sendResult = client.getAcsResponse(request);
            String code = (String) ReflectUtil.getFieldValue(sendResult, "code");
            String message = (String) ReflectUtil.getFieldValue(sendResult, "message");
            String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId");
            // 解析结果
            R data = null;
            if (Objects.equals(code, "OK")) {
                // 请求成功的情况下
                data = responseConsumer.apply(sendResult);
            }
            // 拼接结果
            return SmsCommonResult.build(code, message, requestId, data);
        } catch (ClientException ex) {
            return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null);
        }
    }

    private static String formatResultMsg(ClientException ex) {
        if (StrUtil.isEmpty(ex.getErrorDescription())) {
            return ex.getErrMsg();
        }
        return ex.getErrMsg() + " => " + ex.getErrorDescription();
    }

}
